home *** CD-ROM | disk | FTP | other *** search
/ Die Speccy' 97 / Die Speccy' 97.iso / amiga_system / the_aminet / util / cli / gengui21.lha / Gengui2.1 / lib / gengui_lnk.c < prev    next >
C/C++ Source or Header  |  1995-10-25  |  42KB  |  1,525 lines

  1.  
  2. #include <stdlib.h>
  3.  
  4. #define __USE_SYSBASE
  5.  
  6. #include <exec/libraries.h>
  7. #include <exec/types.h>
  8. #include <proto/exec.h>
  9. #include <proto/gadtools.h>
  10. #include <libraries/gadtools.h>
  11. #include <proto/intuition.h>
  12. #include <intuition/intuition.h>
  13. #include <proto/graphics.h>
  14. #include <graphics/text.h>
  15. #include <string.h>
  16. #include <intuition/gadgetclass.h>
  17. #include <proto/layers.h>
  18. #include <proto/utility.h>
  19.  
  20. #include "gengui.h"
  21.  
  22. #if MWDEBUG
  23. #include <exec/memory.h>
  24. #include <sc:extras/memlib/memwatch.h>
  25. #endif
  26.  
  27. #define TextID SRx
  28.  
  29. #ifndef max
  30. #define max(x,y) ((x)>(y)?(x):(y))
  31. #endif
  32. #ifndef min
  33. #define min(x,y) ((x)<(y)?(x):(y))
  34. #endif
  35.  
  36. #ifdef USE_LOCALE
  37. #include <libraries/locale.h>
  38. #include <proto/locale.h>
  39. extern struct Catalog *Catalog;
  40. #define GetTextStr(gad) (Catalog?(const char *)GetCatalogStr(Catalog,(gad)->Dim.TextID,(STRPTR)(gad)->Text):(gad)->Text)
  41. #else
  42. #define GetTextStr(gad) (gad)->Text
  43. #endif
  44.  
  45.  
  46. ULONG Modify[]={0,0,GTCB_Checked,GTIN_Number,GTLV_Selected,
  47.                           GTMX_Active,0,GTCY_Active,GTPA_Color,
  48.                           GTSC_Top,0,GTSL_Level,GTST_String,0};
  49.  
  50. ULONG Default[]={0,0,FALSE,0,~0,0,0,0,1,0,0,0,(ULONG)"",0};
  51.  
  52. static ULONG *MergeTags(ULONG *oldlist,ULONG *newlist)
  53. /* oldlist enthΣlt als ersten Eintrag die LΣnge des Arrays, genauso
  54.    die zurⁿckgegebene Liste */
  55. {
  56.    ULONG *p;
  57.    if(!oldlist) {
  58.       oldlist=malloc(16*sizeof(ULONG));
  59.       if(!oldlist) return(NULL);
  60.       oldlist[0]=16;
  61.       oldlist[1]=TAG_DONE;
  62.    }
  63.  
  64.    while(*newlist!=TAG_DONE) {
  65.       switch(*newlist) {
  66.          case TAG_IGNORE:  newlist+=2;
  67.                            break;
  68.          case TAG_MORE:    newlist=(ULONG *)newlist[1];
  69.                            break;
  70.          case TAG_SKIP:    newlist+=2*newlist[1]+2;
  71.                            break;
  72.          default:
  73.  
  74.                            p=oldlist+1;
  75.  
  76.             /* passenden Eintrag in der Taglist suchen, bzw Ende der Liste */
  77.  
  78.                            while(*p!=TAG_DONE && *p!=*newlist) p+=2;
  79.  
  80.                            if(*p==*newlist) {
  81.                               p[1]=newlist[1]; /* alte Daten ueberschreiben */
  82.                               newlist+=2;
  83.                            } else {
  84.                               int n=p-oldlist; /* Position im Array; */
  85.  
  86.                               if(n>=oldlist[0]-1) { /* Array vergr÷▀ern */
  87.                                  ULONG *mem;
  88.                                  mem=realloc(oldlist,oldlist[0]+16*sizeof(ULONG));
  89.                                  if(!mem) return(NULL);
  90.                                  oldlist=mem;
  91.                                  oldlist[0]+=16;
  92.                                  p=oldlist+n;
  93.                               }
  94.  
  95.                               *p++=*newlist++;
  96.                               *p++=*newlist++;
  97.                               *p=TAG_DONE;
  98.                            }
  99.                            break;
  100.       }
  101.    }
  102.    return(oldlist);
  103. }
  104.  
  105. BOOL GG_SetGadgetAttrsA(struct Gadget *gad,struct Window *win,
  106.                        struct Requester *req, ULONG *Tag)
  107. {
  108.    ULONG *newtags;
  109.    struct GadInfo *gi;
  110.  
  111.    gi=GetInfo(gad);
  112.  
  113.    if(gi->Dim.Kind==GG_GFXBUTTON_KIND) {
  114.  
  115.       if(Tag[0]==GA_Disabled) { /* Only this tag is supported */
  116.          struct Gadget *g;
  117.  
  118.          g=(struct Gadget *)gi->SaveTags;
  119.  
  120.          if( !(g->Flags & GFLG_DISABLED) != !Tag[1]) {
  121.             int index;
  122.  
  123.             index=RemoveGadget(win,gad);
  124.  
  125.             if(index!=65535) {
  126.                gad->Flags^=GFLG_DISABLED;
  127.                EraseRect(win->RPort,gad->LeftEdge,gad->TopEdge,gad->LeftEdge+gad->Width-1,gad->TopEdge+gad->Height-1);
  128.                AddGadget(win,gad,index);
  129.                RefreshGList(gad,win,req,1);
  130.             }
  131.  
  132.          }
  133.          return TRUE;
  134.       }
  135.       return FALSE;
  136.    }
  137.  
  138.  
  139.    if(gi->Dim.Kind<0) return FALSE;
  140.  
  141.    if(!gi->SaveTags) {
  142.       gi->SaveTags=MergeTags(NULL,gi->Tags);
  143.       if(!gi->SaveTags) return(FALSE);
  144.    }
  145.  
  146.    newtags=MergeTags(gi->SaveTags,Tag);
  147.    if(!newtags) return(FALSE);
  148.    gi->SaveTags=newtags;
  149.    GT_SetGadgetAttrsA(gad,win,req,(struct TagItem *)Tag);
  150.    return(TRUE);
  151. }
  152. BOOL GG_SetGadgetAttrs(struct Gadget *gad,struct Window *win,
  153.                        struct Requester *req, ULONG Tag1,...)
  154. {
  155.    return(GG_SetGadgetAttrsA(gad,win,req,&Tag1));
  156. }
  157.  
  158. BOOL GG_SetLowlevelAttrsA(struct GadInfo *gad, ULONG *Tag)
  159. {
  160.    ULONG *newtags;
  161.  
  162.    if(gad->Dim.Kind<0) return FALSE;
  163.  
  164.    if(!gad->SaveTags) {
  165.       gad->SaveTags=MergeTags(NULL,gad->Tags);
  166.       if(!gad->SaveTags) return(FALSE);
  167.    }
  168.  
  169.    newtags=MergeTags(gad->SaveTags,Tag);
  170.    if(!newtags) return(FALSE);
  171.    gad->SaveTags=newtags;
  172.    return(TRUE);
  173. }
  174. BOOL GG_SetLowlevelAttrs(struct GadInfo *gad, ULONG Tag1,...)
  175. {
  176.    return(GG_SetLowlevelAttrsA(gad,&Tag1));
  177. }
  178.  
  179. static int MakeGTGadget(struct WinInfo *winfo,                       /**/
  180.                             struct GadInfo *gad,
  181.                             int left, int top, int width, int height)
  182. {
  183.    struct NewGadget ng;
  184.  
  185.    if(winfo->Mode==GG_MODE_REFRESH && gad->Dim.Kind>=0) return(0);
  186.  
  187.    ng.ng_LeftEdge=left + (gad->Dim.XSpace>>1);
  188.    ng.ng_TopEdge=top + (gad->Dim.YSpace>>1);
  189.    ng.ng_Width=width - gad->Dim.XSpace;
  190.    ng.ng_Height=height - gad->Dim.YSpace;
  191.    ng.ng_GadgetText=(char *)GetTextStr(gad);
  192.    ng.ng_TextAttr=gad->TextAttr ? gad->TextAttr : &winfo->TextAttr;
  193.    ng.ng_GadgetID=gad->GadgetID;
  194.    ng.ng_Flags=gad->Flags;
  195.    ng.ng_VisualInfo=winfo->Visual;
  196.    ng.ng_UserData=(void *)gad;
  197.  
  198.    if(gad->Dim.Kind>=0) {
  199.       /* Falls dies kein erneutes aufsetzen ist: SaveTags neu errechnen */
  200.       if(!gad->SaveTags) { /* || (!(winfo->Box->Dim.Flags & GG_FLAG_BACKUP) && winfo->Mode==GG_MODE_NEW)) { */
  201.          ULONG *tags;
  202.          static ULONG modifytag[]={0,0,TAG_DONE};
  203.  
  204.          if(gad->SaveTags) free(gad->SaveTags);
  205.          gad->SaveTags=NULL;
  206.  
  207.          if(Modify[gad->Dim.Kind]) { /* Allocate savetags for use with GG_GetIMsg() */
  208.             modifytag[0]=Modify[gad->Dim.Kind];
  209.             modifytag[1]=Default[gad->Dim.Kind];
  210.             tags=MergeTags(NULL,modifytag);
  211.             if(!tags) return(1);
  212.             gad->SaveTags=tags;
  213.          }
  214.          tags=MergeTags(gad->SaveTags,gad->Tags);
  215.          if(!tags) return(1);
  216.          gad->SaveTags=tags;
  217.       }
  218.  
  219.       winfo->Prev=gad->ThisGad=winfo->Gadgets[gad->GadNum]=
  220.           CreateGadgetA(gad->Dim.Kind,winfo->Prev,&ng,(struct TagItem *)(gad->SaveTags+1));
  221.       if(winfo->Prev==NULL) return(1); else return(0);
  222.    } else {
  223.       return(gad->CustomFunc(winfo,&ng,gad,left,top,width,height));
  224.    }
  225. } /**/
  226.  
  227. void GG_GfxPrintSize(struct RastPort *rast,const char *text,struct GG_ObjectSize *size)
  228. {
  229.    int x;
  230.    const char *p;
  231.    struct RastPort rp;
  232.    struct TextExtent ext;
  233.  
  234.    rp=*rast;
  235.  
  236.    SetSoftStyle(&rp,FS_NORMAL,-1);
  237.  
  238.    size->Height=rp.Font->tf_YSize;
  239.    size->Width=0;
  240.  
  241.    x=0;
  242.  
  243.    for(p=text;*p;p++) {
  244.  
  245.       if(*p=='\n') {
  246.  
  247.          if(p-text>0) {
  248.             TextExtent(&rp,(char *)text,p-text,&ext);
  249.             x+=ext.te_Extent.MaxX-ext.te_Extent.MinX+1;
  250.             if(x>size->Width) size->Width=x;
  251.             x=0;
  252.             size->Height+=rp.Font->tf_YSize;
  253.          }
  254.          text=p+1;
  255.  
  256.       } else if(*p=='%') {
  257.  
  258.          if(p[1]=='%') {
  259.             p++;
  260.             TextExtent(&rp,(char *)text,p-text,&ext);
  261.             x+=ext.te_Extent.MaxX-ext.te_Extent.MinX+1;
  262.             text=p+1;
  263.  
  264.          } else {
  265.  
  266.             if(p-text>0) {
  267.                TextExtent(&rp,(char *)text,p-text,&ext);
  268.                x+=ext.te_Extent.MaxX-ext.te_Extent.MinX+1;
  269.             }
  270.  
  271.             p++;
  272.  
  273.             switch(*p) {
  274.  
  275.                case 'C': p++; break;
  276.                case 'c': p++; break;
  277.  
  278.                case 'I': SetSoftStyle(&rp,FSF_ITALIC,FSF_ITALIC);break;
  279.                case 'i': SetSoftStyle(&rp,0,FSF_ITALIC);break;
  280.                case 'B': SetSoftStyle(&rp,FSF_BOLD,FSF_BOLD);break;
  281.                case 'b': SetSoftStyle(&rp,0,FSF_BOLD);break;
  282.                case 'U': SetSoftStyle(&rp,FSF_UNDERLINED,FSF_UNDERLINED);break;
  283.                case 'u': SetSoftStyle(&rp,0,FSF_UNDERLINED);break;
  284.  
  285.                case 'N': SetSoftStyle(&rp,FS_NORMAL,-1);break;
  286.  
  287.                default: break;
  288.             }
  289.  
  290.             text=p+1;
  291.          }
  292.       }
  293.    }
  294.  
  295.    if(p-text>0) {
  296.       TextExtent(&rp,(char *)text,p-text,&ext);
  297.       x+=ext.te_Extent.MaxX-ext.te_Extent.MinX+1;
  298.       if(x>size->Width) size->Width=x;
  299.    }
  300. }
  301. void GG_GfxPrint(struct RastPort *rast,const char *text,int left,int top)
  302. {
  303.    struct RastPort rp;
  304.    int x;
  305.    const char *p;
  306.  
  307.    rp=*rast;
  308.  
  309.    SetDrMd(&rp,JAM2);
  310.    SetAPen(&rp,1);
  311.    SetBPen(&rp,0);
  312.    SetSoftStyle(&rp,FS_NORMAL,-1);
  313.  
  314.    top+=rp.Font->tf_Baseline;
  315.    x=left;
  316.  
  317.    for(p=text;*p;p++) {
  318.  
  319.       if(*p=='\n') {
  320.  
  321.          if(p-text>0) {
  322.             Move(&rp,x,top);
  323.             Text(&rp,(char *)text,p-text);
  324.             x=left;
  325.             top+=rp.Font->tf_YSize;
  326.          }
  327.          text=p+1;
  328.  
  329.       } else if(*p=='%') {
  330.  
  331.          if(p[1]=='%') {
  332.             p++;
  333.             Move(&rp,x,top);
  334.             Text(&rp,(char *)text,p-text);
  335.             x+=TextLength(&rp,(char *)text,p-text);
  336.             text=p+1;
  337.  
  338.          } else {
  339.  
  340.             if(p-text>0) {
  341.                Move(&rp,x,top);
  342.                Text(&rp,(char *)text,p-text);
  343.                x+=TextLength(&rp,(char *)text,p-text);
  344.             }
  345.  
  346.             p++;
  347.  
  348.             switch(*p) {
  349.  
  350.                case 'C': p++;SetAPen(&rp,*p-'0');break;
  351.                case 'c': p++;SetBPen(&rp,*p-'0');break;
  352.  
  353.                case 'I': SetSoftStyle(&rp,FSF_ITALIC,FSF_ITALIC);break;
  354.                case 'i': SetSoftStyle(&rp,0,FSF_ITALIC);break;
  355.                case 'B': SetSoftStyle(&rp,FSF_BOLD,FSF_BOLD);break;
  356.                case 'b': SetSoftStyle(&rp,0,FSF_BOLD);break;
  357.                case 'U': SetSoftStyle(&rp,FSF_UNDERLINED,FSF_UNDERLINED);break;
  358.                case 'u': SetSoftStyle(&rp,0,FSF_UNDERLINED);break;
  359.  
  360.                case 'N': SetSoftStyle(&rp,FS_NORMAL,-1);break;
  361.  
  362.                default: break;
  363.             }
  364.  
  365.             text=p+1;
  366.          }
  367.       }
  368.    }
  369.  
  370.    if(p-text>0) {
  371.       Move(&rp,x,top);
  372.       Text(&rp,(char *)text,p-text);
  373.    }
  374. }
  375.  
  376. static int MakePlainText(struct WinInfo *winfo,                      /**/
  377.                           struct GadInfo *gad,
  378.                           int left,int top,int width,int height)
  379. {
  380.    struct TextFont *newfont=NULL,*oldfont;
  381.  
  382.    if(!winfo->Render) return 0;
  383.  
  384.    if(gad->TextAttr) {
  385.       newfont=OpenFont(gad->TextAttr);
  386.       if(!newfont) return 1;
  387.  
  388.       oldfont=winfo->Window->RPort->Font;
  389.       SetFont(winfo->Window->RPort,newfont);
  390.    }
  391.  
  392.  
  393.    if(gad->Flags) {
  394.  
  395.       struct GG_ObjectSize size;
  396.  
  397.       GG_GfxPrintSize(winfo->Window->RPort,GetTextStr(gad),&size);
  398.  
  399.       width-=gad->Dim.XSpace;
  400.       height-=gad->Dim.YSpace;
  401.  
  402.       if(gad->Flags & GG_HCentered) {
  403.          left+=width-size.Width>>1;
  404.       } else if(gad->Flags & GG_Right) {
  405.          left+=width-size.Width;
  406.       }
  407.  
  408.       if(gad->Flags & GG_VCentered) {
  409.          top+=height-size.Height>>1;
  410.       } else if(gad->Flags & GG_Bottom) {
  411.          top+=height-size.Height;
  412.       }
  413.    }
  414.  
  415.    GG_GfxPrint(winfo->Window->RPort,GetTextStr(gad),left+(gad->Dim.XSpace>>1)
  416.                                           ,top+(gad->Dim.YSpace>>1));
  417.  
  418.    if(newfont) {
  419.       SetFont(winfo->Window->RPort,oldfont);
  420.       CloseFont(newfont);
  421.    }
  422.  
  423.    return 0;
  424.  
  425. }
  426. static int MakeGfxButton(struct WinInfo *winfo,                      /**/
  427.                           struct GadInfo *gad,
  428.                           int left,int top,int width,int height)
  429. {
  430.    struct Gadget *g;
  431.  
  432.    ULONG flags;
  433.  
  434.    if(winfo->Mode != GG_MODE_NEW && winfo->Mode !=GG_MODE_RESIZE) return 0;
  435.  
  436.    width-=gad->Dim.XSpace;
  437.    height-=gad->Dim.YSpace;
  438.    left+=gad->Dim.XSpace>>1;
  439.    top+=gad->Dim.YSpace>>1;
  440.  
  441.    flags=gad->Flags;
  442.  
  443.    if(!gad->SaveTags && !(gad->SaveTags=calloc(1,sizeof(struct Gadget))))
  444.          return 1;
  445.  
  446.    g=(struct Gadget *)gad->SaveTags;
  447.  
  448.    g->LeftEdge=left;
  449.    g->TopEdge=top;
  450.    g->Width=width;
  451.    g->Height=height;
  452.  
  453.    if((flags ^ GG_FullSize) && gad->Tags[0]) {
  454.  
  455.       // limit the size to the size of the image or align the image within
  456.       // the allocated space
  457.  
  458.       struct Image *i,*i2;
  459.  
  460.       i=(struct Image *)gad->Tags[0];
  461.       i2=(struct Image *)gad->Tags[1];
  462.  
  463.       // align the button within the allocated room
  464.  
  465.       // horizontal centered
  466.  
  467.       if(flags & GG_HCentered) {
  468.          i->LeftEdge=width-i->Width>>1;
  469.          if(i2) i2->LeftEdge=width-i->Width>>1;
  470.       } else if(flags & GG_Right) {
  471.          i->LeftEdge=width-i->Width;
  472.          if(i2) i2->LeftEdge=width-i->Width;
  473.       }
  474.  
  475.       // vertical centered
  476.  
  477.       if(flags & GG_VCentered) {
  478.          i->TopEdge=height-i->Height>>1;
  479.          if(i2) i2->TopEdge=height-i->Height>>1;
  480.       } else if(flags & GG_Bottom) {
  481.          i->TopEdge=height-i->Height;
  482.          if(i2) i2->TopEdge=height-i->Height;
  483.       }
  484.  
  485.       // limit the size to that of the image
  486.  
  487.       if(!(flags & GG_FullSize)) {
  488.          g->LeftEdge=left+i->LeftEdge;
  489.          g->TopEdge=top+i->TopEdge;
  490.          g->Width=i->Width;
  491.          g->Height=i->Height;
  492.  
  493.          i->LeftEdge=0;
  494.          i->TopEdge=0;
  495.  
  496.          if(i2) {
  497.             i2->LeftEdge=0;
  498.             i2->TopEdge=0;
  499.          }
  500.       }
  501.  
  502.    }
  503.  
  504.    if(!gad->Code) { /* gad->Code==1 tells, that the gadget is already */
  505.                     /* initialized for resize or after GG_StopGui     */
  506.       gad->Code=1;
  507.  
  508.       flags&=~GG_IgnoreFlags;
  509.  
  510.       g->Flags=GFLG_GADGIMAGE
  511.                   | (gad->Tags[0]&&gad->Tags[1]?GFLG_GADGHIMAGE:GFLG_GADGHCOMP)
  512.                   | (flags & 0xffff);
  513.  
  514.       g->Activation=flags>>16;
  515.  
  516.  
  517.  
  518.       g->GadgetType=GTYP_BOOLGADGET;
  519.  
  520.       g->GadgetRender=(void *)(gad->Tags[0]);
  521.       g->SelectRender=(void *)(gad->Tags[0]?gad->Tags[1]:0);
  522.  
  523.       g->GadgetID=gad->GadgetID;
  524.  
  525.       g->UserData=gad;
  526.    }
  527.  
  528.    winfo->Prev->NextGadget=g;
  529.    winfo->Prev=gad->ThisGad=winfo->Gadgets[gad->GadNum]=g;
  530.  
  531.    return 0;
  532. }
  533.  
  534. static int MakeGuiGadget(struct WinInfo *winfo,                      /**/
  535.                           struct Box *box,
  536.                           int left,int top,int width,int height)
  537. {
  538.    struct Box **p;
  539.    int relx,rely,absx,absy;
  540.    int w,h;
  541.  
  542.    left+=box->Dim.LeftCSpace*winfo->FontX+box->Dim.LeftPSpace;
  543.    width-=(box->Dim.LeftCSpace+box->Dim.RightCSpace)*winfo->FontX
  544.           +box->Dim.LeftPSpace+box->Dim.RightPSpace;
  545.  
  546.    top+=box->Dim.TopCSpace*winfo->FontX+box->Dim.TopPSpace;
  547.    height-=(box->Dim.TopCSpace+box->Dim.BottomCSpace)*winfo->FontX
  548.           +box->Dim.TopPSpace+box->Dim.BottomPSpace;
  549.  
  550.    if(box->Dim.Kind>0 || box->Dim.Kind==GG_CUSTOM_KIND)
  551.                          return(MakeGTGadget(winfo,(struct GadInfo *)box,
  552.                                                  left,top,width,height));
  553.  
  554.    if(box->Dim.Kind==GG_PLAINTEXT_KIND)
  555.                          return MakePlainText(winfo,(struct GadInfo *)box,
  556.                                               left,top,width,height);
  557.    if(box->Dim.Kind==GG_GFXBUTTON_KIND)
  558.                          return MakeGfxButton(winfo,(struct GadInfo *)box,
  559.                                               left,top,width,height);
  560.  
  561.    if(!winfo->Render) {
  562.       for(p=box->Entry;*p;p++) {
  563.          if(MakeGuiGadget(winfo,(*p),0,0,0,0)) return(1);
  564.       }
  565.    } else {
  566.  
  567.       if(box->Dim.Flags & (GG_FLAG_RAISED | GG_FLAG_RECESSED)) {
  568.  
  569.          if(box->Backfill) {
  570.             struct Hook *old;
  571.  
  572.             old=InstallLayerHook(winfo->Window->RPort->Layer,box->Backfill);
  573.             EraseRect(winfo->Window->RPort,left+(box->Dim.XSpace>>1),
  574.                                          top+(box->Dim.YSpace>>1),
  575.                                          left+(box->Dim.XSpace>>1)+width-box->Dim.XSpace-1,
  576.                                          top+(box->Dim.YSpace>>1)+height-box->Dim.YSpace-1);
  577.             InstallLayerHook(winfo->Window->RPort->Layer,old);
  578.          }
  579.  
  580.          DrawBevelBox(winfo->Window->RPort,
  581.                         left+(box->Dim.XSpace>>1),
  582.                         top+(box->Dim.YSpace>>1),
  583.                         width-box->Dim.XSpace,
  584.                         height-box->Dim.YSpace,
  585.                 (box->Dim.Flags & GG_FLAG_RAISED)?TAG_IGNORE:GTBB_Recessed,TRUE,
  586.                         GT_VisualInfo,winfo->Visual,
  587.                         TAG_DONE);
  588.  
  589.          left+=box->Dim.XSpace;
  590.          top+=box->Dim.YSpace;
  591.          width-=2*box->Dim.XSpace;
  592.          height-=2*box->Dim.YSpace;
  593.  
  594.       } else {
  595.          if(box->Backfill) {
  596.             struct Hook *old;
  597.  
  598.             old=InstallLayerHook(winfo->Window->RPort->Layer,box->Backfill);
  599.             EraseRect(winfo->Window->RPort,left,top,
  600.                                          left+width-1,
  601.                                          top+height-1);
  602.             InstallLayerHook(winfo->Window->RPort->Layer,old);
  603.          }
  604.  
  605.          if(box->Dim.Flags & GG_FLAG_BAR) {
  606.             struct DrawInfo *dinfo;
  607.             struct RastPort rast;
  608.  
  609.             rast=*winfo->Window->RPort;
  610.  
  611.             dinfo=GetScreenDrawInfo(winfo->Window->WScreen);
  612.  
  613.             if(box->Dim.Kind==GG_HBOX) {
  614.  
  615.                SetAPen(&rast,dinfo->dri_Pens[SHADOWPEN]);
  616.                Move(&rast,left,top);
  617.                Draw(&rast,left+width-1,top);
  618.  
  619.                SetAPen(&rast,dinfo->dri_Pens[SHINEPEN]);
  620.                Move(&rast,left,top+1);
  621.                Draw(&rast,left+width-1,top+1);
  622.  
  623.             } else {
  624.  
  625.                SetAPen(&rast,dinfo->dri_Pens[SHADOWPEN]);
  626.                Move(&rast,left,top);
  627.                Draw(&rast,left,top+height-1);
  628.  
  629.                SetAPen(&rast,dinfo->dri_Pens[SHINEPEN]);
  630.                Move(&rast,left+1,top);
  631.                Draw(&rast,left+1,top+height-1);
  632.  
  633.             }
  634.  
  635.             FreeScreenDrawInfo(winfo->Window->WScreen,dinfo);
  636.          }
  637.       }
  638.  
  639.       if(!box->Entry) return(0);
  640.  
  641.       relx=box->Dim.SRx;
  642.       rely=box->Dim.SRy;
  643.       absx=box->Dim.SPx;
  644.       absy=box->Dim.SPy;
  645.  
  646.       if(box->Dim.Kind==GG_HBOX) {
  647.  
  648.          width-=absx;
  649.          if(width<0) width=0;
  650.  
  651.          for(p=box->Entry;*p;p++) {
  652.             w=width * ((*p)->Dim.Rx)/relx + (*p)->Dim.Px;
  653.             h=height * ((*p)->Dim.Ry)/rely + (*p)->Dim.Py;
  654.  
  655.             if(MakeGuiGadget(winfo,(*p),left,top,w,h)) return(1);
  656.  
  657.             left+=w;
  658.          }
  659.  
  660.       } else if(box->Dim.Kind==GG_VBOX) {
  661.  
  662.          height-=absy;
  663.          if(height<0) height=0;
  664.  
  665.          for(p=box->Entry;*p;p++) {
  666.             w=width * ((*p)->Dim.Rx)/relx + (*p)->Dim.Px;
  667.             h=height * ((*p)->Dim.Ry)/rely + (*p)->Dim.Py;
  668.  
  669.             if(MakeGuiGadget(winfo,(*p),left,top,w,h)) return(1);
  670.  
  671.             top+=h;
  672.          }
  673.  
  674.       }
  675.    }
  676.    return(0);
  677. }          /**/
  678. static void FreeGuiGadget(struct Box *box)
  679. {
  680.    struct Box **p;
  681.  
  682.    struct GadInfo *gad;
  683.  
  684.    if(box->Dim.Kind>0) {
  685.       gad=(struct GadInfo *)box;
  686.       if(gad->SaveTags) free(gad->SaveTags);
  687.       gad->SaveTags=NULL;
  688.  
  689.       if(box->Dim.Kind==STRING_KIND) {
  690.          if(gad->Code) free((void *)gad->Code);
  691.          gad->Code=NULL;
  692.       }
  693.    } else if(box->Dim.Kind==GG_GFXBUTTON_KIND) {
  694.       gad=(struct GadInfo *)box;
  695.       gad->Code=0; /* delete flag for using old gadget-flags */
  696.  
  697.    } else {
  698.  
  699.       if(   (box->Dim.Kind!=GG_VBOX && box->Dim.Kind!=GG_HBOX)
  700.          || !box->Entry) return;
  701.  
  702.       for(p=box->Entry;*p;p++) FreeGuiGadget(*p);
  703.    }
  704. }
  705.  
  706. static void InitGui(struct WinInfo *winfo,struct Box *box)           /**/
  707. {
  708.    struct Box **p;
  709.    struct GadInfo *gad;
  710.  
  711.    int relx=0,rely=0,absx=0,absy=0;
  712.  
  713.    if(box->Dim.Kind==BUTTON_KIND) {
  714.       gad=(struct GadInfo *)box;
  715.  
  716.       if(!(box->Dim.MinCx | box->Dim.MinPx)) {
  717.          box->Dim.MinCx=gad->Text?strlen(GetTextStr(gad)):1;
  718.          box->Dim.MinPx=4;
  719.       }
  720. #if 0 /* bereits in defaults eingestellt */
  721.       if(!(box->Dim.MinCy | box->Dim.MinPy)) {
  722.          box->Dim.MinCy=1;
  723.          box->Dim.MinPy=4;
  724.       }
  725. #endif
  726.    } else if(box->Dim.Kind==CYCLE_KIND) {
  727.       char **label;
  728.       int len=1;
  729.  
  730.       gad=(struct GadInfo *)box;
  731.  
  732.       if(!(box->Dim.MinCx | box->Dim.MinPx)) {
  733.  
  734.          if(gad->Tags && (label=(char **)GetTagData(GTCY_Labels,NULL,(struct TagItem *)gad->Tags))) {
  735.             char **p;
  736.             int n;
  737.  
  738.             for(p=label;*p;p++) {
  739.                n=strlen(*p);
  740.                if(n>len) len=n;
  741.             }
  742.          }
  743.  
  744.          box->Dim.MinCx=len;
  745.          box->Dim.MinPx=24;
  746.       }
  747.  
  748.    } else if(box->Dim.Kind==MX_KIND) {
  749.       char **label;
  750.       int cnt=0;
  751.  
  752.       gad=(struct GadInfo *)box;
  753.  
  754.       if(!(box->Dim.MinCy | box->Dim.MinPy)) {
  755.  
  756.          if(gad->Tags && (label=(char **)GetTagData(GTMX_Labels,NULL,(struct TagItem *)gad->Tags))) {
  757.             char **p;
  758.             for(p=label;*p;p++) cnt++;
  759.          }
  760.  
  761.          box->Dim.MinCy=cnt;
  762.          box->Dim.MinPy=6;
  763.       }
  764.  
  765.    } else if(box->Dim.Kind==GG_PLAINTEXT_KIND) {
  766.  
  767.       if(!(box->Dim.MinCx|box->Dim.MinPx) || !(box->Dim.MinCy|box->Dim.MinPy)) {
  768.  
  769.          struct GG_ObjectSize size;
  770.          gad=(struct GadInfo *)box;
  771.  
  772.          GG_GfxPrintSize(winfo->Window->RPort,GetTextStr(gad),&size);
  773.  
  774.  
  775.          if(!(box->Dim.MinCx | box->Dim.MinPx) || (box->Dim.Flags & GG_FLAG_DEFAULT_WIDTH)) {
  776.             box->Dim.Flags |= GG_FLAG_DEFAULT_WIDTH;
  777.             box->Dim.MinPx=size.Width;
  778.          }
  779.  
  780.          if(!(box->Dim.MinCy | box->Dim.MinPy) || (box->Dim.Flags & GG_FLAG_DEFAULT_HEIGHT)) {
  781.             box->Dim.Flags |= GG_FLAG_DEFAULT_HEIGHT;
  782.             box->Dim.MinPy=size.Height;
  783.          }
  784.       }
  785.    } else if(box->Dim.Kind==GG_GFXBUTTON_KIND) {
  786.  
  787.       if(!(box->Dim.MinCx|box->Dim.MinPx)) {
  788.  
  789.          struct Image *i,*i2;
  790.  
  791.          gad=(struct GadInfo *)box;
  792.          i=(struct Image *)gad->Tags[0];
  793.          i2=(struct Image *)gad->Tags[1];
  794.  
  795.          if(i) box->Dim.MinPx=i->Width;
  796.          if(i2 && i2->Width>i->Width) box->Dim.MinPx=i2->Width;
  797.  
  798.       }
  799.  
  800.       if(!(box->Dim.MinCy|box->Dim.MinPy)) {
  801.  
  802.          struct Image *i,*i2;
  803.  
  804.          gad=(struct GadInfo *)box;
  805.          i=(struct Image *)gad->Tags[0];
  806.          i2=(struct Image *)gad->Tags[1];
  807.  
  808.  
  809.          if(i) box->Dim.MinPy=i->Height;
  810.          if(i2 && i2->Height>i->Height) box->Dim.MinPy=i2->Height;
  811.  
  812.       }
  813.    }
  814.  
  815.    box->Dim.Px+=box->Dim.Cx*winfo->FontX;
  816.    box->Dim.Py+=box->Dim.Cy*winfo->FontY;
  817.  
  818.    box->Dim.MinPx+=box->Dim.MinCx*winfo->FontX;
  819.    box->Dim.MinPy+=box->Dim.MinCy*winfo->FontY;
  820.  
  821.    if(!box->Entry || box->Dim.Kind>0 || box->Dim.Kind==GG_CUSTOM_KIND) {
  822.       return;
  823.    }
  824.  
  825.    for(p=box->Entry;*p;p++) InitGui(winfo,*p);
  826.  
  827.    if(box->Dim.Kind==GG_HBOX) {
  828.  
  829.       for(p=box->Entry;*p;p++) {
  830.          relx+=(*p)->Dim.Rx;
  831.          absx+=(*p)->Dim.Px;
  832.  
  833.          rely=max(rely,(*p)->Dim.Ry);
  834.          absy=max(absy,(*p)->Dim.Py);
  835.       }
  836.    } else {
  837.       for(p=box->Entry;*p;p++) {
  838.          rely+=(*p)->Dim.Ry;
  839.          absy+=(*p)->Dim.Py;
  840.  
  841.          relx=max(relx,(*p)->Dim.Rx);
  842.          absx=max(absx,(*p)->Dim.Px);
  843.       }
  844.    }
  845.  
  846.    if(relx==0) relx=1;
  847.    if(rely==0) rely=1;
  848.  
  849.    box->Dim.SRx=relx;
  850.    box->Dim.SRy=rely;
  851.    box->Dim.SPx=absx;
  852.    box->Dim.SPy=absy;
  853.  
  854.    for(p=box->Entry;*p;p++) {
  855.       box->Dim.Flags|=(*p)->Dim.Flags & GG_FLAG_TRADEMASK;
  856.    }
  857.  
  858.    return;
  859. }          /**/
  860. static void DeInitGui(struct WinInfo *winfo,struct Box *box)           /**/
  861. {
  862.    struct Box **p;
  863.  
  864.    box->Dim.Px-=box->Dim.Cx*winfo->FontX;
  865.    box->Dim.Py-=box->Dim.Cy*winfo->FontY;
  866.  
  867.    box->Dim.MinPx-=box->Dim.MinCx*winfo->FontX;
  868.    box->Dim.MinPy-=box->Dim.MinCy*winfo->FontY;
  869.  
  870.    if(!box->Entry || box->Dim.Kind>0 || box->Dim.Kind==GG_CUSTOM_KIND) {
  871.       return;
  872.    }
  873.  
  874.    for(p=box->Entry;*p;p++) DeInitGui(winfo,*p);
  875.  
  876.    return;
  877. }          /**/
  878. static int BackupGui(struct WinInfo *winfo,struct Box *box)          /**/
  879. {
  880.    struct GadInfo *gad=(struct GadInfo *)box;
  881.    int err=0;
  882.  
  883.    if(box->Dim.Flags & (GG_FLAG_STRING | GG_FLAG_INTEGER)) {
  884.  
  885.       if(box->Dim.Kind==INTEGER_KIND) {
  886.          ULONG tags[]={GTIN_Number,0,TAG_DONE};
  887.          tags[1]=GetNumber(gad->ThisGad);
  888.          MergeTags(gad->SaveTags,tags);
  889. /*         gad->Code=GetNumber(gad->ThisGad); */
  890.       } else if(box->Dim.Kind==STRING_KIND) {
  891.  
  892.          /* gad->Code is used to store the pointer to the memory */
  893.  
  894.          ULONG tags[]={GTST_String,0,TAG_DONE};
  895.          if(gad->Code) free((void *)gad->Code);
  896.          gad->Code=(ULONG)strdup(GetString(gad->ThisGad));
  897.          if(!gad->Code) return(1);
  898.          tags[1]=gad->Code;
  899.          MergeTags(gad->SaveTags,tags); /* This is always successful, since
  900.                                          * there is always a GTST_String tag
  901.                                          * in the taglist (see MakeGTGadget) */
  902.       } else if(box->Dim.Kind==GG_VBOX || box->Dim.Kind==GG_HBOX) {
  903.          struct Box **p;
  904.  
  905.          if(!box->Entry) return(0);
  906.  
  907.          for(p=box->Entry; *p; p++) {
  908.             err|=BackupGui(winfo,*p);
  909.          }
  910.       }
  911.    }
  912.    return(err);
  913. } /**/
  914. static void FindCustom(struct WinInfo *winfo,struct Box *box)        /**/
  915. {
  916.    struct GadInfo *gad=(struct GadInfo *)box;
  917.    static struct NewGadget ng; /* Just to avoid Enforcer Hits */
  918.  
  919.    if( !(box->Dim.Flags & GG_FLAG_CUSTOM)) return;
  920.  
  921.    if(box->Dim.Kind==GG_CUSTOM_KIND) {
  922.       gad->CustomFunc(winfo,&ng,gad,0,0,0,0);
  923.    } else if(box->Dim.Kind==GG_VBOX || box->Dim.Kind==GG_HBOX) {
  924.       struct Box **p;
  925.  
  926.       if(box->Dim.Flags & GG_FLAG_CUSTOM) {
  927.          if(!box->Entry) return;
  928.  
  929.          for(p=box->Entry; *p; p++) {
  930.             FindCustom(winfo,*p);
  931.          }
  932.       }
  933.    }
  934. } /**/
  935.  
  936. struct IntuiMessage *GG_GetIMsg(struct MsgPort *userport) /**/
  937. {
  938.    struct IntuiMessage *msg;
  939.    int ignore=1;
  940.    struct Gadget *gad;
  941.  
  942.    while(ignore && (msg=GT_GetIMsg(userport))) {
  943.  
  944.       ignore=0;
  945.  
  946.       switch(msg->Class) {
  947.          case IDCMP_MOUSEMOVE:
  948.          case IDCMP_GADGETUP:
  949.          case IDCMP_GADGETDOWN:
  950.             gad=(struct Gadget *)msg->IAddress;
  951.             if(gad && gad->GadgetID>=0) {
  952.                struct GadInfo *gi;
  953.                ULONG tags[]={0,0,TAG_DONE};
  954.                gi=GetInfo(gad);
  955.  
  956.                if(gi->Dim.Kind>=0 && Modify[gi->Dim.Kind]) {
  957.                   tags[0]=Modify[gi->Dim.Kind];
  958.                   tags[1]=msg->Code;
  959.                   MergeTags(gi->SaveTags,tags); /* always successful in this case */
  960.                }
  961.                if(GetInfo(gad)->HookFunc) ignore=GetInfo(gad)->HookFunc(msg);
  962.             }
  963.             break;
  964.       }
  965.       if(ignore) {
  966.          GT_ReplyIMsg(msg);
  967.       }
  968.    }
  969.    return msg;
  970. } /**/
  971.  
  972. void GG_ClearWindow(struct Window *win)
  973. {
  974.    RefreshWindowFrame(win);
  975.    EraseRect(win->RPort,win->BorderLeft,
  976.                         win->BorderTop,
  977.                         win->Width-1-win->BorderRight,
  978.                         win->Height-1-win->BorderBottom);
  979. }
  980.  
  981. int GG_RenderGui(struct Window *win, struct WinInfo *winfo)             /**/
  982. {
  983.    winfo->Window=win;
  984.    winfo->Mode=GG_MODE_NEW;
  985.    winfo->Render=1;
  986.  
  987.    AskFont(win->RPort,&winfo->TextAttr);
  988.  
  989.    winfo->FontX = win->RPort->Font->tf_XSize;
  990.    winfo->FontY = win->RPort->Font->tf_YSize;
  991.    winfo->Visual=GetVisualInfoA(win->WScreen,NULL);
  992.  
  993.    if(!(winfo->Box->Dim.Flags & GG_FLAG_INITED)) {
  994.       winfo->Box->Dim.Flags |= GG_FLAG_INITED;
  995.       InitGui(winfo,winfo->Box);
  996.    }
  997.  
  998.    if(!winfo->Visual) goto exit_fail2;
  999.  
  1000.    if(!CreateContext(&winfo->GList)) return(1);
  1001.  
  1002.    winfo->Prev=winfo->GList;
  1003.  
  1004.    if(MakeGuiGadget(winfo,winfo->Box,win->BorderLeft,win->BorderTop,
  1005.                      win->Width - win->BorderLeft - win->BorderRight,
  1006.                      win->Height - win->BorderTop - win->BorderBottom))
  1007.                                                              goto exit_fail3;
  1008.    AddGList(win,winfo->GList,-1,-1,NULL);
  1009.    RefreshGList(winfo->GList,win,NULL,-1);
  1010.    GT_RefreshWindow(win,NULL);
  1011.  
  1012.    if(winfo->Box->Dim.Flags & GG_FLAG_BACKUP) {
  1013.       winfo->Mode=GG_MODE_RESTORE;
  1014.       FindCustom(winfo,winfo->Box);
  1015.       winfo->Box->Dim.Flags &= ~GG_FLAG_BACKUP;
  1016.    }
  1017.  
  1018.    return(0);
  1019.  
  1020. exit_fail3:
  1021.    if(winfo->GList) FreeGadgets(winfo->GList);
  1022.    FreeVisualInfo(winfo->Visual);
  1023. exit_fail2:
  1024.    return(1);
  1025. }  /**/
  1026. int GG_ResizeGui(struct WinInfo *winfo)                                 /**/
  1027. {
  1028.    struct Window *win=winfo->Window;
  1029.  
  1030.    if(winfo->GList) {
  1031.  
  1032.       winfo->Box->Dim.Flags|=GG_FLAG_SKIPREFRESH|GG_FLAG_RESIZED;
  1033.       winfo->Mode=GG_MODE_BACKUP;
  1034.       winfo->Render=0;
  1035.  
  1036.       FindCustom(winfo,winfo->Box); /* Backup of customgadgets */
  1037.  
  1038.       BackupGui(winfo,winfo->Box);
  1039.  
  1040.       winfo->Mode=GG_MODE_RESIZE;
  1041.       winfo->Render=1;
  1042.  
  1043.       RemoveGList(win,winfo->GList,-1);
  1044.       FreeGadgets(winfo->GList);
  1045.  
  1046.       winfo->GList=NULL;
  1047.    }
  1048.  
  1049.    if(winfo->Box->Backfill==NULL) GG_ClearWindow(win); else RefreshWindowFrame(win);
  1050.  
  1051.    if(!CreateContext(&winfo->GList)) return(1);
  1052.    winfo->Prev=winfo->GList;
  1053.  
  1054.    if(MakeGuiGadget(winfo,winfo->Box,win->BorderLeft,win->BorderTop,
  1055.                      win->Width - win->BorderLeft - win->BorderRight,
  1056.                      win->Height - win->BorderTop - win->BorderBottom))
  1057.                                                                   return(2);
  1058.  
  1059.    AddGList(win,winfo->GList,-1,-1,NULL);
  1060.    RefreshGList(winfo->GList,win,NULL,-1);
  1061.  
  1062.    GT_RefreshWindow(win,NULL);
  1063.  
  1064.    winfo->Mode=GG_MODE_RESTORE;
  1065.    winfo->Render=0;
  1066.    FindCustom(winfo,winfo->Box);
  1067.  
  1068.    return(0);
  1069. }  /**/
  1070. void GG_BeginResizeGui(struct WinInfo *winfo)
  1071. {
  1072.    struct Window *win=winfo->Window;
  1073.  
  1074.    if(winfo->GList) {
  1075.  
  1076.       winfo->Mode=GG_MODE_BACKUP;
  1077.       winfo->Render=0;
  1078.  
  1079.       FindCustom(winfo,winfo->Box); /* Backup of customgadgets */
  1080.  
  1081.       BackupGui(winfo,winfo->Box);
  1082.  
  1083.       winfo->Mode=GG_MODE_RESIZE;
  1084.       winfo->Render=1;
  1085.  
  1086.       RemoveGList(win,winfo->GList,-1);
  1087.       FreeGadgets(winfo->GList);
  1088.  
  1089.       winfo->GList=NULL;
  1090.    }
  1091. }
  1092.  
  1093. int GG_RefreshGui(struct WinInfo *winfo)                                /**/
  1094. {
  1095.    struct Window *win=winfo->Window;
  1096.  
  1097.    if(winfo->Box->Dim.Flags&GG_FLAG_SKIPREFRESH) {
  1098.       winfo->Box->Dim.Flags&=~GG_FLAG_SKIPREFRESH;
  1099.       return(0);
  1100.    }
  1101.  
  1102.    if(!winfo->GList) return 0;
  1103.  
  1104.    winfo->Render=1;
  1105.    winfo->Mode=GG_MODE_REFRESH;
  1106.    if(MakeGuiGadget(winfo,winfo->Box,win->BorderLeft,win->BorderTop,
  1107.                     win->Width - win->BorderLeft - win->BorderRight,
  1108.                     win->Height - win->BorderTop - win->BorderBottom)) return(1);
  1109.  
  1110.    RefreshGList(winfo->GList,win,NULL,-1);
  1111. #if 0
  1112.    GT_RefreshWindow(winfo->Window,NULL);
  1113. #endif
  1114.    return 0;
  1115. }         /**/
  1116.  
  1117. void GG_BeginRefresh(struct WinInfo *winfo)
  1118. {
  1119.    if(!(winfo->Box->Dim.Flags & GG_FLAG_RESIZED)) {
  1120.       GT_BeginRefresh(winfo->Window);
  1121.    }
  1122. }
  1123. void GG_EndRefresh(struct WinInfo *winfo, BOOL complete)
  1124. {
  1125.    if(!(winfo->Box->Dim.Flags & GG_FLAG_RESIZED)) {
  1126.       GT_EndRefresh(winfo->Window,complete);
  1127.    } else {
  1128.       if(complete) {
  1129.          GT_BeginRefresh(winfo->Window);
  1130.          GT_EndRefresh(winfo->Window,TRUE);
  1131.       }
  1132.    }
  1133.    if(complete) winfo->Box->Dim.Flags &= ~GG_FLAG_RESIZED;
  1134. }
  1135.  
  1136. static void FreeStopGui(struct WinInfo *winfo,int backup)                       /**/
  1137. {
  1138.    winfo->Render=0;
  1139.    if(backup) {
  1140.       winfo->Mode=GG_MODE_BACKUP;
  1141.       BackupGui(winfo,winfo->Box);
  1142.       FindCustom(winfo,winfo->Box);
  1143.       winfo->Box->Dim.Flags|=GG_FLAG_BACKUP;
  1144.       winfo->Mode=GG_MODE_STOP;
  1145.       FindCustom(winfo,winfo->Box);
  1146.    } else {
  1147.       winfo->Mode=GG_MODE_FREE;
  1148.       FindCustom(winfo,winfo->Box);
  1149.       FreeGuiGadget(winfo->Box);
  1150.    }
  1151.  
  1152.    if(winfo->GList) {
  1153.       RemoveGList(winfo->Window,winfo->GList,-1);
  1154.       FreeGadgets(winfo->GList);
  1155.       winfo->GList=NULL;
  1156.    }
  1157.    if(winfo->Visual) {
  1158.       FreeVisualInfo(winfo->Visual);
  1159.       winfo->Visual=NULL;
  1160.    }
  1161.  
  1162.    if(winfo->Box->Dim.Flags & GG_FLAG_INITED) {
  1163.       winfo->Box->Dim.Flags &= ~GG_FLAG_INITED;
  1164.       DeInitGui(winfo,winfo->Box);
  1165.    }
  1166. } /**/
  1167. void GG_FreeGui(struct WinInfo *winfo)
  1168. {
  1169.    FreeStopGui(winfo,0);
  1170. }
  1171. void GG_StopGui(struct WinInfo *winfo)
  1172. {
  1173.    FreeStopGui(winfo,1);
  1174. }
  1175.  
  1176. static int RenderSubGui(struct WinInfo *winfo,                              /**/
  1177.                  int left,int top,int width, int height)
  1178. {
  1179.    InitGui(winfo,winfo->Box);
  1180.  
  1181.    if(MakeGuiGadget(winfo,winfo->Box,left,top,width,height)) return(1);
  1182.  
  1183.    return(0);
  1184. } /**/
  1185. static int ResizeSubGui(struct WinInfo *winfo,                              /**/
  1186.                  int left, int top,int width,int height)
  1187. {
  1188.    if(MakeGuiGadget(winfo,winfo->Box,left,top,width,height)) return(1);
  1189.  
  1190.    return(0);
  1191. } /**/
  1192. static int RefreshSubGui(struct WinInfo *winfo,int left,int top,int width,int height) /**/
  1193. {
  1194.    winfo->Mode=GG_MODE_REFRESH;
  1195.    return(MakeGuiGadget(winfo,winfo->Box,left,top,width,height));
  1196. } /**/
  1197. static void FreeSubGui(struct WinInfo *winfo)                               /**/
  1198. {
  1199.    winfo->Mode=GG_MODE_FREE;
  1200.    FindCustom(winfo,winfo->Box);
  1201.    FreeGuiGadget(winfo->Box);
  1202.    DeInitGui(winfo,winfo->Box);
  1203. }                                         /**/
  1204. static void StopSubGui(struct WinInfo *winfo)                               /**/
  1205. {
  1206.    winfo->Mode=GG_MODE_STOP;
  1207.    FindCustom(winfo,winfo->Box);
  1208.    DeInitGui(winfo,winfo->Box);
  1209. }                                         /**/
  1210.  
  1211. int GG_SubGui(struct WinInfo *parent, struct WinInfo *winfo,            /**/
  1212.                   int left,int top,int width, int height)
  1213. {
  1214.    int ret=0;
  1215.  
  1216.    memcpy((void *)(((ULONG)winfo)+2*sizeof(void *)),
  1217.           (void *)(((ULONG)parent)+2*sizeof(void *)),
  1218.           sizeof(struct WinInfo)-2*sizeof(void *));
  1219.  
  1220.    switch(parent->Mode) {
  1221.  
  1222.       case GG_MODE_NEW:  ret=RenderSubGui(winfo,left,top,width,height);
  1223.                          winfo->Box->Dim.Flags&=~GG_FLAG_BACKUP;
  1224.                          break;
  1225.       case GG_MODE_RESIZE:
  1226.                          ret=ResizeSubGui(winfo,left,top,width,height);
  1227.                          winfo->Box->Dim.Flags&=~GG_FLAG_BACKUP;
  1228.                          break;
  1229.       case GG_MODE_REFRESH:
  1230.                          ret=RefreshSubGui(winfo,left,top,width,height);
  1231.                          break;
  1232.       case GG_MODE_STOP: StopSubGui(winfo);
  1233.                          break;
  1234.       case GG_MODE_FREE: FreeSubGui(winfo);
  1235.                          break;
  1236.       case GG_MODE_RESTORE:
  1237.                          FindCustom(winfo,winfo->Box);
  1238.                          break;
  1239.       case GG_MODE_BACKUP:
  1240.                          ret=BackupGui(winfo,winfo->Box);
  1241.                          FindCustom(winfo,winfo->Box);
  1242.                          winfo->Box->Dim.Flags|=GG_FLAG_BACKUP;
  1243.                          break;
  1244.    }
  1245.    parent->Prev=winfo->Prev;
  1246.    return(ret);
  1247. }  /**/
  1248. static void GetMinSize(struct WinInfo *winfo,                      /**/
  1249.                           struct Box *box,
  1250.                           struct GG_ObjectSize *size)
  1251. {
  1252.    struct Box **p;
  1253.    int relx,rely,absx,absy;
  1254.    int w,h;
  1255.  
  1256.  
  1257.    if(box->Dim.Kind>0 || box->Dim.Kind<=GG_CUSTOM_KIND) {
  1258.  
  1259.       size->Width=box->Dim.MinPx+box->Dim.XSpace
  1260.                  +(box->Dim.LeftCSpace+box->Dim.RightCSpace)*winfo->FontX
  1261.                  +box->Dim.LeftPSpace+box->Dim.RightPSpace;
  1262.       size->Height=box->Dim.MinPy+box->Dim.YSpace
  1263.                  +(box->Dim.TopCSpace+box->Dim.BottomCSpace)*winfo->FontY
  1264.                  +box->Dim.TopPSpace+box->Dim.BottomPSpace;
  1265.  
  1266.       if(!box->Dim.Rx) size->Width=box->Dim.Px;
  1267.       if(!box->Dim.Ry) size->Height=box->Dim.Py;
  1268.  
  1269.    } else {
  1270.  
  1271.       struct GG_ObjectSize osize;
  1272.       int rwidth,rheight;
  1273.  
  1274.       size->Width=size->Height=0;
  1275.  
  1276.       if(!box->Entry) return;
  1277.       if(box->Dim.Flags & GG_FLAG_BAR) return; /* wird bereits beim Init berⁿcksichtigt */
  1278.  
  1279.       /* Sonderbehandlung, falls explizit angegeben */
  1280.  
  1281.       if((box->Dim.MinCx|box->Dim.MinPx) && (box->Dim.MinCy|box->Dim.MinPy)) {
  1282.          size->Width=box->Dim.MinPx+box->Dim.XSpace
  1283.                  +(box->Dim.LeftCSpace+box->Dim.RightCSpace)*winfo->FontX
  1284.                  +box->Dim.LeftPSpace+box->Dim.RightPSpace;
  1285.          size->Height=box->Dim.MinPy+box->Dim.YSpace
  1286.                  +(box->Dim.TopCSpace+box->Dim.BottomCSpace)*winfo->FontY
  1287.                  +box->Dim.TopPSpace+box->Dim.BottomPSpace;
  1288.          return;
  1289.       }
  1290.  
  1291.  
  1292.       if(!box->Dim.Rx && !box->Dim.Ry) {
  1293.          size->Width=box->Dim.Px;
  1294.          size->Height=box->Dim.Py;
  1295.          return;
  1296.       }
  1297.  
  1298.       relx=box->Dim.SRx;
  1299.       rely=box->Dim.SRy;
  1300.       absx=box->Dim.SPx;
  1301.       absy=box->Dim.SPy;
  1302.  
  1303.       if(box->Dim.Kind==GG_HBOX) {
  1304.  
  1305.          rheight=absy;
  1306.          rwidth=0;
  1307.  
  1308.          for(p=box->Entry;*p;p++) {
  1309.  
  1310.             if((*p)->Dim.Rx || (*p)->Dim.Ry) GetMinSize(winfo,*p,&osize);
  1311.  
  1312.             if((*p)->Dim.Rx) {
  1313.                w=(osize.Width+(*p)->Dim.Rx-1)/(*p)->Dim.Rx*relx;
  1314.                rwidth=max(rwidth,w);
  1315.             }
  1316.  
  1317.             if((*p)->Dim.Ry) {
  1318.                h=(osize.Height+(*p)->Dim.Ry-1)/(*p)->Dim.Ry*rely;
  1319.                rheight=max(rheight,h);
  1320.             }
  1321.          }
  1322.  
  1323.          size->Width=rwidth+absx;
  1324.          size->Height=rheight;
  1325.       } else {
  1326.  
  1327.          rheight=0;
  1328.          rwidth=absx;
  1329.  
  1330.          for(p=box->Entry;*p;p++) {
  1331.  
  1332.             if((*p)->Dim.Rx || (*p)->Dim.Ry) GetMinSize(winfo,*p,&osize);
  1333.  
  1334.             if((*p)->Dim.Ry) {
  1335.                h=(osize.Height+(*p)->Dim.Ry-1)/(*p)->Dim.Ry*rely;
  1336.                rheight=max(rheight,h);
  1337.             }
  1338.  
  1339.             if((*p)->Dim.Rx) {
  1340.                w=(osize.Width+(*p)->Dim.Rx-1)/(*p)->Dim.Rx*relx;
  1341.                rwidth=max(rwidth,w);
  1342.             }
  1343.          }
  1344.  
  1345.          size->Width=rwidth;
  1346.          size->Height=rheight+absy;
  1347.       }
  1348.  
  1349.       if(box->Dim.Flags & (GG_FLAG_RAISED | GG_FLAG_RECESSED)) {
  1350.  
  1351.          size->Width+=2*box->Dim.XSpace;
  1352.          size->Height+=2*box->Dim.YSpace;
  1353.       }
  1354.  
  1355.       /* Explizit angegebene Werte ⁿberschreiben berechnete */
  1356.  
  1357.       if(box->Dim.MinCx|box->Dim.MinPx) size->Width=box->Dim.MinPx+box->Dim.XSpace;
  1358.       if(box->Dim.MinCy|box->Dim.MinPy) size->Height=box->Dim.MinPy+box->Dim.YSpace;
  1359.  
  1360.       size->Width+=(box->Dim.LeftCSpace+box->Dim.RightCSpace)*winfo->FontX
  1361.                    +box->Dim.LeftPSpace+box->Dim.RightPSpace;
  1362.  
  1363.       size->Height+=(box->Dim.TopCSpace+box->Dim.BottomCSpace)*winfo->FontY
  1364.                     +box->Dim.TopPSpace+box->Dim.BottomPSpace;
  1365.  
  1366.       if(!box->Dim.Rx) size->Width=box->Dim.Px;
  1367.       if(!box->Dim.Ry) size->Height=box->Dim.Py;
  1368.    }
  1369.  
  1370.    return;
  1371. }          /**/
  1372.  
  1373. void GG_MinSize(struct Window *win, struct WinInfo *winfo,struct GG_ObjectSize *size)
  1374. {
  1375.    int inited=0;
  1376.    struct Window *oldwin;
  1377.  
  1378.    oldwin=winfo->Window;
  1379.  
  1380.    if(winfo->Box->Dim.Flags & GG_FLAG_INITED) {
  1381.       inited=1;
  1382.       if(winfo->Window!=win) {
  1383.          DeInitGui(winfo,winfo->Box);
  1384.          winfo->Window=win;
  1385.          winfo->FontX = winfo->Window->RPort->Font->tf_XSize;
  1386.          winfo->FontY = winfo->Window->RPort->Font->tf_YSize;
  1387.          InitGui(winfo,winfo->Box);
  1388.       }
  1389.    } else {
  1390.       winfo->Window=win;
  1391.       winfo->FontX = winfo->Window->RPort->Font->tf_XSize;
  1392.       winfo->FontY = winfo->Window->RPort->Font->tf_YSize;
  1393.       InitGui(winfo,winfo->Box);
  1394.    }
  1395.  
  1396.    GetMinSize(winfo,winfo->Box,size);
  1397.  
  1398.    if(inited) {
  1399.       if(oldwin!=winfo->Window) {
  1400.          DeInitGui(winfo,winfo->Box);
  1401.          winfo->Window=oldwin;
  1402.          winfo->FontX = winfo->Window->RPort->Font->tf_XSize;
  1403.          winfo->FontY = winfo->Window->RPort->Font->tf_YSize;
  1404.          InitGui(winfo,winfo->Box);
  1405.       }
  1406.    } else {
  1407.       DeInitGui(winfo,winfo->Box);
  1408.    }
  1409. }
  1410. void GG_MinSizeFont(struct TextFont *font,struct WinInfo *winfo,struct GG_ObjectSize *size)
  1411. {
  1412.    struct Window win;
  1413.    struct RastPort rp;
  1414.  
  1415.    win.RPort=&rp;
  1416.    InitRastPort(&rp);
  1417.  
  1418.    SetFont(&rp,font);
  1419.  
  1420.    GG_MinSize(&win,winfo,size);
  1421.    return;
  1422. }
  1423.  
  1424. static struct TextAttr topaz={
  1425.    "topaz.font",TOPAZ_EIGHTY,FS_NORMAL,FPF_ROMFONT};
  1426.  
  1427. int GG_SmartRenderGui(struct Window *win, struct WinInfo *winfo,struct TextFont **font)
  1428. {
  1429.    struct GG_ObjectSize size;
  1430.    int left,top,width,height;
  1431.    ULONG idcmp;
  1432.    short changed;
  1433.  
  1434.    GG_MinSize(win,winfo,&size);
  1435.  
  1436.    size.Width+=win->BorderLeft+win->BorderRight;
  1437.    size.Height+=win->BorderTop+win->BorderBottom;
  1438.  
  1439.    if(size.Width>win->WScreen->Width || size.Height>win->WScreen->Height) {
  1440.  
  1441.       if(*font || (*font=OpenFont(&topaz))) {
  1442.          SetFont(win->RPort,*font);
  1443.       }
  1444.  
  1445.       GG_MinSize(win,winfo,&size);
  1446.       size.Width+=win->BorderLeft+win->BorderRight;
  1447.       size.Height+=win->BorderTop+win->BorderBottom;
  1448.    }
  1449.  
  1450.    if(size.Width>win->WScreen->Width) size.Width=win->WScreen->Width;
  1451.    if(size.Height>win->WScreen->Height) size.Height=win->WScreen->Height;
  1452.  
  1453.  
  1454.    Forbid();
  1455.  
  1456.    if(size.Width<=win->Width && size.Height<=win->Height) {
  1457.  
  1458.       /* Window is large enough, just set Windowlimits */
  1459.  
  1460.       WindowLimits(win,size.Width,size.Height,-1,-1);
  1461.       Permit();
  1462.       return GG_RenderGui(win,winfo);
  1463.    }
  1464.  
  1465.    Permit();
  1466.  
  1467.  
  1468.    /* Calculate the new window-dimensions */
  1469.  
  1470.    left=win->LeftEdge;
  1471.    top=win->TopEdge;
  1472.    width=win->Width;
  1473.    height=win->Height;
  1474.  
  1475.    if(size.Width>width) width=size.Width;
  1476.    if(size.Height>height) height=size.Height;
  1477.    if(left+width>win->WScreen->Width) left=win->WScreen->Width-width;
  1478.    if(top+height>win->WScreen->Height) top=win->WScreen->Height-height;
  1479.  
  1480.    idcmp=win->IDCMPFlags;
  1481.    if(!ModifyIDCMP(win,(idcmp|IDCMP_CHANGEWINDOW) & ~IDCMP_NEWSIZE))
  1482.             return 1; /* Could not Modify IDCMP */
  1483.  
  1484.    WindowLimits(win,0,0,-1,-1);
  1485.    ChangeWindowBox(win,left,top,width,height);
  1486.  
  1487.    changed=0;
  1488.  
  1489.    while(!changed) { /* Wait until the window has changed it dimensions, */
  1490.                      /* but keep all other Messages                      */
  1491.  
  1492.       struct IntuiMessage *msg,*succ;
  1493.  
  1494.       Wait(1<<win->UserPort->mp_SigBit);
  1495.  
  1496.       Forbid();
  1497.  
  1498.       for(msg=(struct IntuiMessage *) win->UserPort->mp_MsgList.lh_Head;
  1499.             (succ=(struct IntuiMessage *)msg->ExecMessage.mn_Node.ln_Succ)
  1500.                && !changed; msg=succ) {
  1501.  
  1502.          if(msg->IDCMPWindow==win && msg->Class==IDCMP_CHANGEWINDOW) {
  1503.  
  1504.             Remove((struct Node *)msg);
  1505.             ReplyMsg((struct Message *)msg);
  1506.             changed=1;
  1507.          }
  1508.       }
  1509.  
  1510.       Permit();
  1511.    }
  1512.  
  1513.    ModifyIDCMP(win,idcmp);
  1514.    WindowLimits(win,size.Width,size.Height,-1,-1);
  1515.  
  1516.    /* The next refresh is caused by IDCMP_CHANGEWINDOW. Since the
  1517.       GUI was not rendered yet, we may skip it */
  1518.  
  1519.    winfo->Box->Dim.Flags|=GG_FLAG_SKIPREFRESH;
  1520.    return GG_RenderGui(win,winfo);
  1521. }
  1522.  
  1523.  
  1524.  
  1525.